﻿using GpCommon.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace GpCommon.Helpers
{
    public class GpLocalDataHelper
    {
        /// <summary>
        /// 获取本地存储的股票代号
        /// </summary>
        /// <returns></returns>
        public static List<string> GetValidGpCodes()
        {
            List<string> codes = new List<string>();

            string str = File.ReadAllText(CommonData.CodeFilePath);
            var strs = str.Split(';');
            foreach (var item in strs)
            {
                var gpCoStr = item.Split(':');
                if (gpCoStr.Count() == 2)
                {
                    codes.Add(gpCoStr[0]);
                }
            }

            return codes;
        }

        /// <summary>
        /// 获取本地存储的股票代号及名称
        /// </summary>
        public static List<Tuple<string, string>> GetValidGps()
        {
            List<Tuple<string, string>> gps = new List<Tuple<string, string>>();
            string str = File.ReadAllText(CommonData.CodeFilePath);
            var strs = str.Split(';');
            foreach (var item in strs)
            {
                var gpCoStr = item.Split(':');
                if (gpCoStr.Count() == 2)
                {
                    gps.Add(new Tuple<string, string>(gpCoStr[0], gpCoStr[1]));
                }
            }
            return gps;
        }

        /// <summary>
        /// 根据代号和时间获取历史日线数据
        /// </summary>
        /// <param name="year"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public static List<GpDayEntity> GetLocalHistoryDayInfoByCode(int year, string code)
        {
            if (CommonData.HistoryDayInfo.ContainsKey(year))
            {
                if (CommonData.HistoryDayInfo[year].ContainsKey(code))
                    return CommonData.HistoryDayInfo[year][code].ToList();
            }
            else
            {
                CommonData.HistoryDayInfo.Add(year, new Dictionary<string, List<GpDayEntity>>());
            }
            List<GpDayEntity> result = new List<GpDayEntity>();
            string filePath = Path.Combine(CommonData.HisInfoFolderPath, year.ToString(), code + ".json");
            if (!File.Exists(filePath)) return result;
            string json = File.ReadAllText(filePath);
            var strs = json.Split(';');
            foreach (var str in strs)
            {
                var tempEnt = GpDayEntity.Create(str);
                if (tempEnt != null)
                    result.Add(tempEnt);
            }

            // 增加前一年数据
            List<GpDayEntity> lastResult = new List<GpDayEntity>();
            string filePath1 = Path.Combine(CommonData.HisInfoFolderPath, (year - 1).ToString(), code + ".json");
            if (File.Exists(filePath1))
            {
                string json1 = File.ReadAllText(filePath1);
                var strs1 = json1.Split(';');
                foreach (var str in strs1)
                {
                    var tempEnt = GpDayEntity.Create(str);
                    if (tempEnt != null)
                        lastResult.Add(tempEnt);
                }
            }
            result.InsertRange(0, lastResult);

            List<float> day5List = new List<float>();
            List<float> day10List = new List<float>();
            List<float> day20List = new List<float>();
            List<float> day60List = new List<float>();
           
            for (int i = 0; i < result.Count; i++)
            {
                #region   计算均线
                day5List.Add(result[i].ClsPrice);
                day10List.Add(result[i].ClsPrice);
                day20List.Add(result[i].ClsPrice);
                day60List.Add(result[i].ClsPrice);
                if (day5List.Count == 6)
                {
                    day5List.RemoveAt(0);
                }
                if (day5List.Count == 5)
                {
                    float total5 = 0f;
                    day5List.ForEach(x => { total5 += x; });
                    result[i].Day5Price = (float)Math.Round(total5 / 5f, 2 , MidpointRounding.AwayFromZero);
                }
                if (day10List.Count == 11)
                {
                    day10List.RemoveAt(0);
                }
                if (day10List.Count == 10)
                {
                    float total10 = 0f;
                    day10List.ForEach(x => { total10 += x; });
                    result[i].Day10Price = (float)Math.Round(total10 / 10f, 2, MidpointRounding.AwayFromZero);
                }
                if (day20List.Count == 21)
                {
                    day20List.RemoveAt(0);
                }
                if (day20List.Count == 20)
                {
                    float total20 = 0f;
                    day20List.ForEach(x => { total20 += x; });
                    result[i].Day20Price = (float)Math.Round(total20 / 20f, 2, MidpointRounding.AwayFromZero);
                }
                if (day60List.Count == 61)
                {
                    day60List.RemoveAt(0);
                }
                if (day60List.Count == 60)
                {
                    float total60 = 0f;
                    day60List.ForEach(x => { total60 += x; });
                    result[i].Day60Price = (float)Math.Round(total60 / 60f, 2, MidpointRounding.AwayFromZero);
                }
                #endregion 计算均线

                #region 计算macd指标
                if(i == 0)
                {
                    result[i].EMA12 = result[i].ClsPrice;
                    result[i].EMA26 = result[i].ClsPrice;
                }
                else
                {
                    result[i].EMA12 = (result[i].ClsPrice - result[i - 1].EMA12) * (2 / 13f) + result[i - 1].EMA12;
                    result[i].EMA26 = (result[i].ClsPrice - result[i - 1].EMA26) * (2 / 27f) + result[i - 1].EMA26;
                }
                result[i].DIF = result[i].EMA12 - result[i].EMA26;

                if(i == 0)
                {
                    result[i].DEA = result[i].DIF * 2 / 10f;
                }
                else
                {
                    result[i].DEA = result[i - 1].DEA * 8 / 10f + result[i].DIF * 2 / 10f;
                }

                result[i].MACD = result[i].DIF - result[i].DEA;
                #endregion 计算macd指标

                #region 计算kdj(21,5,5)指标
                int rsvKey = 21;
                int kKey = 5;
                int dKey = 5;
                List<GpDayEntity> tempList;
                if (i < rsvKey - 1)
                {
                    tempList = result.GetRange(0, i + 1);
                }
                else
                {
                    tempList = result.GetRange(i - (rsvKey - 1), rsvKey);
                }
                float maxPrice = tempList.Max(x => x.ClsPrice);
                float minPrice = tempList.Min(x => x.ClsPrice);
                result[i].RSV = ((result[i].ClsPrice - minPrice) / (maxPrice - minPrice)) * 100;
                if(i == 0)
                {
                    result[i].K = 50;
                    result[i].D = 50;
                }
                else
                {
                    result[i].K = ((kKey - 1) / kKey) * result[i - 1].K + (1 / kKey) * result[i].RSV;
                    result[i].D = ((dKey - 1) / dKey) * result[i - 1].D + (1 / dKey) * result[i].K;
                }
                result[i].J = 3 * result[i].K - 2 * result[i].D;
                #endregion 计算kdj指标
            }

            if (result.Count > 0)
            {
                result = result.GetRange(lastResult.Count(), result.Count - lastResult.Count());
                CommonData.HistoryDayInfo[year].Add(code, result);
            }
            return result.ToList();
        }

        /// <summary>
        /// 根据代号获取5分分时数据
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static List<GpDayMSEntity> GetDay5MSEntitiesByCode(int year, string code)
        {
            try
            {
                if (CommonData.History5MSInfo.ContainsKey(year))
                {
                    if (CommonData.History5MSInfo[year].ContainsKey(code))
                        return CommonData.History5MSInfo[year][code];
                }
                else
                {
                    CommonData.History5MSInfo.Add(year, new Dictionary<string, List<GpDayMSEntity>>());
                }
                string rootPath = Path.Combine(CommonData.His5MSInfoFolderPath, year.ToString());
                if (!Directory.Exists(rootPath))
                    return null;
                string tempFile = Path.Combine(rootPath, code + ".txt");
                if (!File.Exists(tempFile))
                    return null;
                List<GpDayMSEntity> ents = new List<GpDayMSEntity>();
                using (FileStream stream = File.OpenRead(tempFile))
                {
                    while (true)
                    {
                        try
                        {
                            byte[] buffer = new byte[32];
                            int bufferCount = stream.Read(buffer, 0, 32);
                            if (bufferCount <= 0) break;
                            GpDayMSEntity ent = GpDayMSEntity.Create(code, buffer);
                            if (ent == null) continue;
                            ents.Add(ent);
                        }
                        catch (Exception ex)
                        {
                            break;
                        }
                    }
                }
                if (ents.Count > 0)
                {
                    float totalTurnVolume = 0f;
                    int totalVolume = 0;
                    // 计算均线值
                    foreach (var item in ents)
                    {
                        if (item.CurTime.Hour == 9 && item.CurTime.Minute == 35)
                        {
                            totalTurnVolume = item.TurnVolume;
                            totalVolume = item.Volume;
                        }
                        else
                        {
                            totalTurnVolume += item.TurnVolume;
                            totalVolume += item.Volume;
                        }

                        item.MidPrice = (float)Math.Round(totalTurnVolume / totalVolume, 2, MidpointRounding.AwayFromZero);
                    }
                    CommonData.History5MSInfo[year].Add(code, ents);
                    return ents;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "获取单一5分时");
            }

            return null;
        }

        /// <summary>
        /// 根据代号获取1分分时数据
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static List<GpDayMSEntity> GetDay1MSEntitiesByCode(int year, string code)
        {
            try
            {
                if (CommonData.History1MSInfo.ContainsKey(year))
                {
                    if (CommonData.History1MSInfo[year].ContainsKey(code))
                        return CommonData.History1MSInfo[year][code];
                }
                else
                {
                    CommonData.History1MSInfo.Add(year, new Dictionary<string, List<GpDayMSEntity>>());
                }
                string rootPath = Path.Combine(CommonData.His1MSInfoFolderPath, year.ToString());
                if (!Directory.Exists(rootPath))
                    return null;
                string tempFile = Path.Combine(rootPath, code + ".txt");
                if (!File.Exists(tempFile))
                    return null;
                List<GpDayMSEntity> ents = new List<GpDayMSEntity>();
                using (FileStream stream = File.OpenRead(tempFile))
                {
                    while (true)
                    {
                        try
                        {
                            byte[] buffer = new byte[32];
                            int bufferCount = stream.Read(buffer, 0, 32);
                            if (bufferCount <= 0) break;
                            GpDayMSEntity ent = GpDayMSEntity.Create(code, buffer);
                            if (ent == null) continue;
                            ents.Add(ent);
                        }
                        catch (Exception ex)
                        {
                            break;
                        }
                    }
                }
                if (ents.Count > 0)
                {
                    float totalTurnVolume = 0f;
                    int totalVolume = 0;
                    // 计算均线值
                    foreach (var item in ents)
                    {
                        if (item.CurTime.Hour == 9 && item.CurTime.Minute == 35)
                        {
                            totalTurnVolume = item.TurnVolume;
                            totalVolume = item.Volume;
                        }
                        else
                        {
                            totalTurnVolume += item.TurnVolume;
                            totalVolume += item.Volume;
                        }

                        item.MidPrice = (float)Math.Round(totalTurnVolume / totalVolume, 2, MidpointRounding.AwayFromZero   );
                    }
                    CommonData.History1MSInfo[year].Add(code, ents);
                    return ents;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "获取单一5分时");
            }

            return null;
        }

    }
}
